﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SilverlightEventing.IdentityMine.Windows.Eventing;


namespace IdentityMine.Windows.Eventing
{
    public static class Extensions
    {
        private static System.Collections.Generic.Dictionary<int, RoutedEventHandlerDataCollection> _GlobalHandlers = new System.Collections.Generic.Dictionary<int, RoutedEventHandlerDataCollection>();

        public static void AddHandlerEx(this UIElement fe, RoutedEventEx routedEvent, Delegate handler)
        {
            fe.AddHandlerEx(routedEvent, handler, false);
        }

        public static void AddHandlerEx(this UIElement fe, RoutedEventEx routedEvent, Delegate handler, bool handledEventsToo)
        {
            RoutedEventHandlerDataCollection coll = null;
            int hash = routedEvent.GetHashCode();

            if (_GlobalHandlers.ContainsKey(hash))
            {
                coll = _GlobalHandlers[hash];
            }
            else
            {
                coll = new RoutedEventHandlerDataCollection();
                _GlobalHandlers.Add(hash, coll);
            }

            coll.AddEntry(new RoutedEventHandlerData(routedEvent, fe, handler, handledEventsToo));
        }

        public static void RaiseEventEx(this UIElement fe, RoutedEventArgsEx args)
        {
            RoutedEventHandlerDataCollection coll = null;
            int hash = args.RoutedEvent.GetHashCode();

            if (_GlobalHandlers.ContainsKey(hash))
            {
                coll = _GlobalHandlers[hash];
            }

            switch (args.RoutingStrategy)
            {
                case RoutingStrategy.Direct:
                    RaiseAgainst(fe, args, coll);
                    break;
                case RoutingStrategy.Bubble:
                    UIElement current = fe;

                    while (current != null)
                    {
                        RaiseAgainst(current, args, coll);
                        UIElement previousCurrent = current;
                        current = VisualTreeHelper.GetParent(current) as UIElement;
                        if (current == previousCurrent) current = null;
                    }

                    break;
            }


            args.Source = args.OriginalSource;
        }

        private static void RaiseAgainst(UIElement fe, RoutedEventArgsEx args, RoutedEventHandlerDataCollection coll)
        {
            if (coll != null)
            {
                coll.RaiseAgainstElement(fe, args);
            }

            RoutedEventHandlerDataCollection collGlobal = EventManagerEx.GetForType(fe.GetType());

            if (collGlobal != null)
            {
                collGlobal.RaiseAgainstEvent(fe,args);
            }
            
        }

        public static void RemoveHandlerEx(this UIElement fe, RoutedEventEx routedEvent, Delegate handler)
        {
            RoutedEventHandlerDataCollection coll = null;
            int hash = routedEvent.GetHashCode();

            if (_GlobalHandlers.ContainsKey(hash))
            {
                coll = _GlobalHandlers[hash];
            }

            if (coll != null)
            {
                RoutedEventHandlerData data = coll.GetFor(handler);
                if (data != null)
                {
                    coll.RemoveEntry(data);
                }
            }
        }
    }
}
